#include "File.h"

using namespace toolkit;

bool FileSystem::createDir(const std::filesystem::path &path) {
    std::error_code ec;
    fs::create_directories(path, ec);
    // 如果创建成功或已经存在且是目录则返回true
    return !ec && fs::is_directory(path);
}

bool FileSystem::createFile(const std::filesystem::path &path) {
    // 1. 确保父目录存在
    if (path.has_parent_path()) {
        if (!createDir(path.parent_path())) {
            return false; // 创建父目录失败
        }
    }
    // 2. 通过打开和关闭文件来创建（或截断）文件
    std::ofstream ofs(path, std::ios::binary | std::ios::trunc);
    return ofs.is_open(); // is_open()检查创建/打开是否成功
}

bool FileSystem::isDir(const std::filesystem::path &path) {
    std::error_code ec;
    bool result = fs::is_directory(path, ec);
    return !ec && result;
}

bool FileSystem::isSpecialDir(const std::filesystem::path &path) {
    fs::path filename = path.filename();
    return !filename.empty() && (filename == "." || filename == "..");
}

bool FileSystem::remove(const std::filesystem::path &path) {
    std::error_code ec;
    return fs::remove(path, ec); // 如果删除成功则返回true，否则返回false
}

bool FileSystem::exists(const std::filesystem::path &path) {
    std::error_code ec;
    bool result = fs::exists(path, ec);
    // 错误可能意味着权限问题等，但通常!exists()涵盖了不存在的情况。
    // 只有当exists()为true且检查时没有错误时才返回true。
    return !ec && result;
}

std::optional<std::string> FileSystem::loadFile(const std::filesystem::path &path) {
    std::error_code ec;
    if (!fs::is_regular_file(path, ec) || ec) {
        return std::nullopt; // 不是常规文件或检查状态出错
    }

    std::ifstream ifs(path, std::ios::in | std::ios::binary);
    if (!ifs) {
        return std::nullopt; // 打开失败
    }

    // 高效读取整个文件的方法
    std::stringstream ss;
    ss << ifs.rdbuf(); // 将流缓冲区读入字符串流
    if (!ifs.good() && !ifs.eof()) { // 检查读取错误（不包括EOF）
        return std::nullopt;
    }

    return ss.str();
}

bool FileSystem::saveFile(const std::string &data, const std::filesystem::path &path) {
    // 1. 确保父目录存在
    if (path.has_parent_path()) {
        if (!createDir(path.parent_path())) {
            return false; // 创建父目录失败
        }
    }

    // 2. 打开文件进行写入（二进制模式，截断现有内容）
    std::ofstream ofs(path, std::ios::out | std::ios::binary | std::ios::trunc);
    if (!ofs) {
        return false; // 打开文件进行写入失败
    }

    // 3. 写入数据
    ofs.write(data.data(), data.size());

    // 4. 检查写入错误并关闭（RAII处理关闭）
    return ofs.good();
}

void FileSystem::scanDir(const std::filesystem::path &path, const std::function<bool (const fs::path &, bool)> &cb, bool recursive, bool show_hidden)
{
    if (!cb || !exists(path) || !isDir(path)) {
        return; // 没有要扫描的内容或回调无效
    }

    std::error_code ec;

    if (recursive) {
        fs::recursive_directory_iterator iter(path, fs::directory_options::skip_permission_denied, ec);
        fs::recursive_directory_iterator end; // 默认构造函数创建结束迭代器

        if (ec) return; // 初始化迭代器出错

        while (iter != end) {
            const fs::directory_entry& entry = *iter;
            try {
                // 隐藏文件检查
                if (!show_hidden && entry.path().filename().string().rfind('.', 0) == 0) {
                    if(iter.recursion_pending()){ // 如果请求，不要跳过隐藏目录的递归
                        iter.disable_recursion_pending();
                    }
                    // 否则只是继续到下一个条目
                } else {
                    bool is_dir = entry.is_directory(ec); // 检查类型
                    if (!ec) {
                        if (!cb(entry.path(), is_dir)) {
                            return; // 回调请求停止
                        }
                    } else {
                        // 检查类型出错，跳过或处理？让我们跳过。
                        ec.clear(); // 清除错误以便可能继续
                    }
                }

                // 安全地推进迭代器
                iter.increment(ec);
                if (ec) {
                    // 推进出错（例如，迭代期间目录被删除），停止迭代
                    break;
                }
            } catch (const std::exception& ex) {
                // 捕获循环内文件系统访问可能的异常
                // 也许记录错误？停止迭代。
                (void)ex; // 避免未使用变量警告
                break;
            }
        }
    } else {
        // 非递归迭代
        fs::directory_iterator iter(path, fs::directory_options::skip_permission_denied, ec);
        fs::directory_iterator end;

        if (ec) return;

        while (iter != end) {
            const fs::directory_entry& entry = *iter;
            try {
                // 隐藏文件检查
                if (!show_hidden && entry.path().filename().string().rfind('.', 0) == 0) {
                    // 跳过隐藏
                } else {
                    bool is_dir = entry.is_directory(ec);
                    if (!ec) {
                        if (!cb(entry.path(), is_dir)) {
                            return; // 回调请求停止
                        }
                    } else {
                        ec.clear(); // 清除错误以便可能继续
                    }
                }
                // 安全地推进迭代器
                iter.increment(ec);
                if (ec) {
                    break; // 推进出错
                }
            } catch (const std::exception& ex) {
                (void)ex;
                break;
            }
        }
    }
}

bool FileSystem::removeEmptyDirectory(const std::filesystem::path &dir_path) {
    std::error_code ec;

    // 检查它是否存在、是目录且为空
    if (!fs::exists(dir_path, ec) || ec || !fs::is_directory(dir_path, ec) || ec) {
        return false;
    }
    bool empty = fs::is_empty(dir_path, ec);
    if (ec || !empty) {
        return false; // 检查空状态出错或不为空
    }

    // 尝试删除
    return fs::remove(dir_path, ec); // 如果删除成功则返回true
}

void FileSystem::removeEmptyDirectoriesRecursive(std::filesystem::path dir_path) {
    std::error_code ec;

    while (true) {
        // 检查当前路径有效性
        if (dir_path.empty() || dir_path == dir_path.root_path()) {
            break; // 在根目录或路径变为空时停止
        }

        // 检查状态：存在、是目录、为空
        if (!fs::exists(dir_path, ec) || ec) break; // 不存在或检查出错
        if (!fs::is_directory(dir_path, ec) || ec) break; // 不是目录或检查出错
        bool empty = fs::is_empty(dir_path, ec);
        if (ec || !empty) break; // 检查空状态出错或不为空

        // 尝试删除
        if (!fs::remove(dir_path, ec) || ec) {
            break; // 删除失败，停止向上递归
        }

        // 移动到父目录进行下一次迭代
        dir_path = dir_path.parent_path();
    }
}

std::optional<uintmax_t> FileSystem::fileSize(const std::filesystem::path &path) {
    std::error_code ec;
    std::uintmax_t size = fs::file_size(path, ec);
    if (ec) {
        return std::nullopt; // 发生错误（例如，未找到、不是文件、权限）
    }
    return size;
}

std::filesystem::path FileSystem::absolutePath(const std::filesystem::path &path, const std::filesystem::path &base_path) {
    std::error_code ec;
    // weakly_canonical解析'..'和'.'，而不需要完整路径存在。
    // fs::absolute在需要时首先转换为绝对路径。
    fs::path p = path.is_absolute() ? path : base_path / path;
    fs::path canonical_path = fs::weakly_canonical(p, ec);
    return ec ? fs::path{} : canonical_path; // 出错时返回空路径
}

std::filesystem::path FileSystem::parentDir(const std::filesystem::path &path) {
    return path.parent_path();
}

uintmax_t FileSystem::removePathRecursive(const std::filesystem::path &path) {
    std::error_code ec;
    // fs::remove_all返回删除的文件/目录数量，出错时返回-1。
    // 如果路径不存在则返回0。
    std::uintmax_t removed_count = fs::remove_all(path, ec);
    return ec ? static_cast<std::uintmax_t>(-1) : removed_count;
}
